//1.传递临时变量的问题
#include<iostream>
#include<thread>

void foo(int& x)
{
	x += 1;
}

int main()
{
	
	//std::thread t(foo, 1);	//1为一个临时变量参数，使用完后立即释放内存，且1是一个右值，参数要求是一个左值
							//就拿不到引用，会报错

	int a = 1;
	std::thread t(foo, std::ref(a));	//用std::ref()修饰
						//a这个变量会被自适应转化成所需的引用变量,变成了右值，
                        //并且由于这个a是在main主线程的局部变量，所以不会报错（详看问题2）

	t.join();
	std::cout << a << std::endl;
	return 0;
}









//2.传递指针或引用指向局部变量的问题
#include<iostream>
#include<thread>

std::thread t;
int ans;
int a=1;	//将a改为全局变量即可

void foo(int& x)
{
	x += 1;
}

void test()
{
	//int a = 1;		//会报错a这个局部变量(在栈上)在test函数结束后就释放了
	t = std::thread(foo, std::ref(a));
    t.join();
    ans = a;
}

int main()
{
	test();
	
	std::cout << ans << std::endl;
	return 0;
}








//3.传递指针或引用指向已经释放的内存的问题
#include<iostream>
#include<thread>

std::thread t;
void foo(int* x)

{
	std::cout << *x << std::endl;
}

int main()
{
	int* ptr = new int(1);
	std::thread t(foo, ptr);
	//delete ptr;	//若线程结束之前手动释放ptr地址，会出错，打印出的是-2


	t.join();
	delete ptr;		//线程结束后再释放即可解决该问题。
	return 0;
}









//4.类成员函数作为入口函数，类对象可能被提前释放
#include<iostream>
#include<thread>
#include<memory>	//智能指针头文件

class Myclass
{
public:
	void func()
	{
		std::cout << "Thread" << std::this_thread::get_id()
			<< "  started" << std::endl;
		//do some work
		std::cout << "Thread" << std::this_thread::get_id()
			<< "  finished" << std::endl;
	}
};

int main()
{
	//Myclass obj;	//若是程序复杂，这个用法不安全，这个obj对象可能会被释放掉，此时程序就会报错
			//用智能指针即可解决这个问题

	std::shared_ptr<Myclass> obj = std::make_shared<Myclass>();		//定义了一个智能指针obj(定义是需要指明类型)
						//当obj对象不再需要时，智能指针会调用析构函数自动释放。

	std::thread t(&Myclass::func, obj);	//此处obj是告诉要执行那个对象的func()函数
									//执行类里面的函数时，要加引用

	t.join();
	return 0;

}











//5.入口函数为类的私有成员函数
#include<iostream>
#include<thread>
#include<memory>
class A
{
private:
	friend void test();		//设置友元
	void foo()
	{
		std::cout << "hello" << std::endl;
	}
};

void test()
{
	std::shared_ptr<A> a = std::make_shared<A>();
	std::thread t(&A::foo, a);		//私有成员变量需要友元才能访问
	t.join();
}

int main()
{
	test();

	return 0;
}
